package com.Pan.util;

import cn.hutool.core.date.DatePattern;
import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 时间处理类
 *
 * @Author: yuyang
 * @Date: 2018-08-23 12:59:08
 */
public class DateUtil {


    public enum DTFormat {
        yyyy_MM_DD_withdot("yyyy.MMM.dd"),
        yyyy_MM_dd("yyyy-MM-dd"), //
        yyyy_MM_dd_HH("yyyy-MM-dd HH"), //
        yyyy_MM_dd_HH_mm("yyyy-MM-dd HH:mm"), //
        yyyy_MM_dd_HH_mm_ss("yyyy-MM-dd HH:mm:ss"), //
        yyyy_MM_dd_HH_mm_ss_SSS("yyyy-MM-dd HH:mm:ss.SSS"), //
        MM_dd_HH_mm_ss("MM-dd HH:mm:ss"), //
        MM_dd_HH_mm("MM-dd HH:mm"), //
        HH_mm("HH:mm"), //
        HH_mm_ss("HH:mm:ss"), //
        yyyyMMdd("yyyyMMdd"), //
        HHmmss("HHmmss"), //
        yyyyMMddHHmmss("yyyyMMddHHmmss"), //
        yyyyMMddHHmmssSSS("yyyyMMddHHmmssSSS"), //
        constomFormat("yyyy年MM月dd日HH点"), //
        yyyy("yyyy"), //
        yyyy_MM("yyyy-MM"), //
        ;

        private String format;
        private int length;

        DTFormat(String format) {
            this.format = format;
            this.length = format.length();
        }

        public String getFormat() {
            return format;
        }

        public int getLength() {
            return length;
        }
    }

    /**
     * 把日期字符串格式化成日期类型
     * @param dateStr
     * @param format
     * @return
     */
    public static Date convert2Date(String dateStr, String format) {
        SimpleDateFormat simple = new SimpleDateFormat(format);
        try {
            simple.setLenient(false);
            return simple.parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
            return  null;
        }
    }


    /**
     * 把日期类型格式化成字符串
     * @param date
     * @param format
     * @return
     */
    public static String convert2String(Date date, String format) {
        SimpleDateFormat formater = new SimpleDateFormat(format);
        try {
            return formater.format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 转sql的time格式
     * @param date
     * @return
     */
    public static java.sql.Timestamp convertSqlTime(Date date){
        java.sql.Timestamp timestamp = new java.sql.Timestamp(date.getTime());
        return timestamp;
    }

    /**
     * 转sql的日期格式
     * @param date
     * @return
     */
    public static java.sql.Date convertSqlDate(Date date){
        java.sql.Date datetamp = new java.sql.Date(date.getTime());
        return datetamp;
    }


    /**
     * 获取当前日期
     * @param format
     * @return
     */
    public static String getCurrentDate(String format) {
        return new SimpleDateFormat(format).format(new Date());
    }

    /**
     * 获取当前日期
     * @date 2018/9/13 下午3:36
     * @return java.util.Date
     */
    public static Date getCurrentDate() {
        return new Date();
    }

    /**
     * 获取时间戳
     * @return
     */
    public static long getTimestamp()
    {
        return System.currentTimeMillis();
    }

    /**
     * 获取月份的天数
     * @param year
     * @param month
     * @return
     */
    public static int getDaysOfMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取日期的年
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获取日期的月
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取日期的日
     * @param date
     * @return
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DATE);
    }

    /**
     * 获取日期的时
     * @param date
     * @return
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR);
    }

    /**
     * 获取日期的分种
     * @param date
     * @return
     */
    public static int getMinute(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MINUTE);
    }

    /**
     * 获取日期的秒
     * @param date
     * @return
     */
    public static int getSecond(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.SECOND);
    }

    /**
     * 获取星期几
     * @param date
     * @return
     */
    public static int getWeekDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek-1;
    }

    /**
     * 获取哪一年共有多少周
     * @param year
     * @return
     */
    public static int getMaxWeekNumOfYear(int year) {
        Calendar c = new GregorianCalendar();
        c.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
        return getWeekNumOfYear(c.getTime());
    }

    /**
     * 取得某天是一年中的多少周
     * @param date
     * @return
     */
    public static int getWeekNumOfYear(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setMinimalDaysInFirstWeek(7);
        c.setTime(date);
        return c.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 取得某天所在周的第一天
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
        return c.getTime();
    }

    /**
     * 取得某天所在周的最后一天
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6);
        return c.getTime();
    }

    /**
     * 取得某年某周的第一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周,2009-01-05为2009年第一周的第一天
     * @param year
     * @param week
     * @return
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        Calendar calFirst = Calendar.getInstance();
        calFirst.set(year, 0, 7);
        Date firstDate = getFirstDayOfWeek(calFirst.getTime());

        Calendar firstDateCal = Calendar.getInstance();
        firstDateCal.setTime(firstDate);

        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, (week - 1) * 7);
        firstDate = getFirstDayOfWeek(cal.getTime());

        return firstDate;
    }

    /**
     * 取得某年某周的最后一天 对于交叉:2008-12-29到2009-01-04属于2008年的最后一周, 2009-01-04为
     * 2008年最后一周的最后一天
     * @param year
     * @param week
     * @return
     */
    public static Date getLastDayOfWeek(int year, int week) {
        Calendar calLast = Calendar.getInstance();
        calLast.set(year, 0, 7);
        Date firstDate = getLastDayOfWeek(calLast.getTime());

        Calendar firstDateCal = Calendar.getInstance();
        firstDateCal.setTime(firstDate);

        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, firstDateCal.get(Calendar.DATE));

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, (week - 1) * 7);
        Date lastDate = getLastDayOfWeek(cal.getTime());

        return lastDate;
    }


    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            c.add(calendarField, amount);
            return c.getTime();
        }
    }

    /*
     * 1则代表的是对年份操作， 2是对月份操作， 3是对星期操作， 5是对日期操作， 11是对小时操作， 12是对分钟操作， 13是对秒操作，
     * 14是对毫秒操作
     */

    /**
     * 增加年
     * @param date
     * @param amount
     * @return
     */
    public static Date addYears(Date date, int amount) {
        return add(date, 1, amount);
    }

    /**
     * 增加月
     * @param date
     * @param amount
     * @return
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, 2, amount);
    }

    /**
     * 增加周
     * @param date
     * @param amount
     * @return
     */
    public static Date addWeeks(Date date, int amount) {
        return add(date, 3, amount);
    }

    /**
     * 增加天
     * @param date
     * @param amount
     * @return
     */
    public static Date addDays(Date date, int amount) {
        return add(date, 5, amount);
    }

    /**
     * 增加时
     * @param date
     * @param amount
     * @return
     */
    public static Date addHours(Date date, int amount) {
        return add(date, 11, amount);
    }

    /**
     * 增加分
     * @param date
     * @param amount
     * @return
     */
    public static Date addMinutes(Date date, int amount) {
        return add(date, 12, amount);
    }

    /**
     * 增加秒
     * @param date
     * @param amount
     * @return
     */
    public static Date addSeconds(Date date, int amount) {
        return add(date, 13, amount);
    }

    /**
     * 增加毫秒
     * @param date
     * @param amount
     * @return
     */
    public static Date addMilliseconds(Date date, int amount) {
        return add(date, 14, amount);
    }



    /**
     * time差
     * @param before
     * @param after
     * @return
     */
    public static long diffTimes(Date before, Date after){
        return after.getTime() - before.getTime();
    }

    /**
     * 秒差
     * @param before
     * @param after
     * @return
     */
    public static long diffSecond(Date before, Date after){
        return (after.getTime() - before.getTime())/1000;
    }

    /**
     * 分种差
     * @param before
     * @param after
     * @return
     */
    public static int diffMinute(Date before, Date after){
        return (int)((after.getTime() - before.getTime())/1000/60);
    }

    /**
     * 时差
     * @param before
     * @param after
     * @return
     */
    public static int diffHour(Date before, Date after){
        return (int)(after.getTime() - before.getTime())/1000/60/60;
    }

    /**
     * 天数差
     * @param before
     * @param after
     * @return
     */
    public static int diffDay(Date before, Date after) {
        return Integer.parseInt(String.valueOf(((after.getTime() - before.getTime()) / 86400000)));
    }

    /**
     * 月差
     * @param before
     * @param after
     * @return
     */
    public static int diffMonth(Date before, Date after){
        int monthAll=0;
        int yearsX = diffYear(before,after);
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(before);
        c2.setTime(after);
        int monthsX = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
        monthAll=yearsX*12+monthsX;
        int daysX =c2.get(Calendar.DATE) - c1.get(Calendar.DATE);
        if(daysX>0){
            monthAll=monthAll+1;
        }
        return monthAll;
    }

    /**
     * 年差
     * @param before
     * @param after
     * @return
     */
    public static int diffYear(Date before, Date after) {
        return getYear(after) - getYear(before);
    }

    /**
     * 设置00:00:00
     * @param date
     * @return
     */
    public static Date setStartDay(Date date) {
        String d = convert2String(date, "yyyy-MM-dd") + " 00:00:00";
        return DateUtil.convert2Date(d, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 设置23:59:59
     * @param date
     * @return
     */
    public static Date setEndDay(Date date) {
        String d = convert2String(date, "yyyy-MM-dd") + " 23:59:59";
        return DateUtil.convert2Date(d, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 根据类型，返回参数日期的格式化字符串
     *
     * @param date
     * @param formatStr
     */
    public static String getFormatDate(Date date, String formatStr) {
        SimpleDateFormat dateformat = getSimpleDateFormat(formatStr);
        return dateformat.format(date);
    }

    /**
     * SimpleDateFormat线程不安全,每次new开销太大
     * @param format
     * @return
     */
    public static SimpleDateFormat getSimpleDateFormat(String format) {
        ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() {
            @Override
            protected SimpleDateFormat initialValue() {
                return new SimpleDateFormat(format);
            }
        };
        return threadLocal.get();
        //return new SimpleDateFormat(format);
    }

    /**
     * 获取指定日期
     * @return
     */
    public static String getDaysAgo(Integer day) {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        calendar.add(Calendar.DATE, day);
        String daysAgo = sdf.format(calendar.getTime());
        return daysAgo;
    }

    /**
     * 获取秒数
     * @param num 数值
     * @param unit 单位
     * @return
     */
    public static long getMinuteByUnit(int num, int unit) {

        if (-1 == unit) {
            // 秒
            return num;
        } else if (0 == unit) {
            // 分
            return num * 60;
        } else if (1 == unit) {
            // 时
            return num * 60 * 60;
        } else if (2 == unit) {
            // 日
            return num * 60 * 60 * 24;
        } else if (3 == unit) {
            // 周
            return num * 60 * 60 * 24 * 7;
        } else if (4 == unit) {
            // 月
            return num * 60 * 60 * 24 * 30;
        } else if (5 == unit) {
            // 年
            return num * 60 * 60 * 24 * 365;
        }

        return num;
    }

    /**
     * 获取秒数，根据时间范围
     * @param startDate
     * @param endDate
     * @return
     */
    public static long getMinuteByRange(String startDate, String endDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long num = 1;
        try {
            num  = (sdf.parse(endDate).getTime() - sdf.parse(startDate).getTime()) / 1000;
        } catch (ParseException e) {
            e.printStackTrace();
            System.out.println(e);
        }
        return num;
    }

    /**
     * 字符串转时间 "yyyy-MM-dd HH:mm:ss.SSS"
     * @param date
     * @return
     */
    public static Date getDateByString (String date) {
        Date datetime = null;
        try {
            datetime = DateUtils.parseDate(date, DatePattern.NORM_DATETIME_MS_PATTERN);
        } catch (ParseException e) {
            System.out.println(e);
        }
        return datetime;
    }

    /**
     * 字符串转时间V2 "yyyy-MM-dd HH:mm:ss"
     * @param date
     * @return
     */
    public static Date getDateByStringV2 (String date) {
        Date datetime = null;
        try {
            datetime = DateUtils.parseDate(date, DatePattern.NORM_DATETIME_PATTERN);
        } catch (ParseException e) {
            System.out.println(e);
        }
        return datetime;
    }

}
